package org.huangrui.redis.iomultiplex.nio;

import cn.hutool.core.util.IdUtil;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.ArrayList;

/**
 * @Author hr
 * @Create 2024-05-24 01:16
 */
public class RedisServerNIO {
    static ArrayList<SocketChannel> socketLists = new ArrayList<>();
    static ByteBuffer byteBuffer = ByteBuffer.allocate(1024);

    public static void main(String[] args) {
        System.out.println("---------RedisServerNIO 启动等待中......");
        try {
            ServerSocketChannel serverSocket = ServerSocketChannel.open();
            serverSocket.bind(new InetSocketAddress(6379));
            serverSocket.configureBlocking(false);
            /**
             * select 其实就是把NIO中用户态要遍历的fd数组(我们的每一个socket链接，安装进ArrayList里面的那个)拷贝到了内核态，
             * 让内核态来遍历，因为用户态判断socket是否有数据还是要调用内核态的，所有拷贝到内核态后，
             * 这样遍历判断的时候就不用一直用户态和内核态频繁切换了
             */
            while (true) {
                for (SocketChannel socketChannel : socketLists) {
                    int read = socketChannel.read(byteBuffer);
                    if (read > 0) {
                        System.out.println("-----读取数据: " + read);
                        byteBuffer.flip();
                        byte[] bytes = new byte[read];
                        byteBuffer.get(bytes);
                        System.out.println(new String(bytes) + IdUtil.simpleUUID());
                        byteBuffer.clear();
                    }
                }
                SocketChannel socketChannel = serverSocket.accept();
                if (socketChannel != null) {
                    System.out.println("-----成功连接: ");
                    socketChannel.configureBlocking(false);// 设置为非阻塞模式
                    socketLists.add(socketChannel);
                    System.out.println("-----socketList size: " + socketLists.size());
                }
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}
